/*
 * Copyright (C) 2013 Square, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
import { ProtocolException } from "../Error/error"
import { Protocol } from "../Protocol"
import { Response } from "../Response"

/** An HTTP response status line like "HTTP/1.1 200 OK". */
export class StatusLine{
  static HTTP_TEMP_REDIRECT = 307
  static HTTP_PERM_REDIRECT = 308
  /** RFC 7540, Section 9.1.2. Retry these if the exchange used connection coalescing. */
  static HTTP_MISDIRECTED_REQUEST = 421
  static HTTP_CONTINUE = 100
  protocol: Protocol
  code: number
  message: string

  constructor(protocol: Protocol, code: number, message: string) {
    this.protocol = protocol
    this.code = code
    this.message = message
  }

  toString(): string {
    let res = ''
    if (this.protocol === Protocol.HTTP_1_0){
      res += 'HTTP/1.0'
    }else{
      res += 'HTTP/1.1'
    }
    res += ' '
    res += this.code
    res += ' '
    res += this.message
    return res
  }



  static get(response: Response): StatusLine {
    return new StatusLine(response.protocol, response.code, response.message)
  }

  // @Throws(IOException::class)
  static parse(statusLine: string): StatusLine {
    // H T T P / 1 . 1   2 0 0   T e m p o r a r y   R e d i r e c t
    // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0

    // Parse protocol like "HTTP/1.1" followed by a space.
    let codeStart: number
    let protocol: Protocol
    if (statusLine.startsWith("HTTP/1.")) {
      if (statusLine.length < 9 || statusLine[8] != ' ') {
        throw new ProtocolException("Unexpected status line: " + statusLine);
      }
      let httpMinorVersion = parseInt(statusLine[7], 10);

      codeStart = 9
      if (httpMinorVersion == 0) {
        protocol = Protocol.HTTP_1_0;
      } else if (httpMinorVersion == 1) {
        protocol = Protocol.HTTP_1_1;
      } else {
        throw new ProtocolException("Unexpected status line: " + statusLine);
      }
    } else if (statusLine.startsWith("ICY ")) {
      // Shoutcast uses ICY instead of "HTTP/1.0".
      protocol = Protocol.HTTP_1_0
      codeStart = 4
    } else {
      throw new ProtocolException("Unexpected status line: " + statusLine);
    }

    // Parse response code like "200". Always 3 digits.
    if (statusLine.length < codeStart + 3) {
      throw new ProtocolException("Unexpected status line: " + statusLine);
    }
    let code: number
    try{
      code = parseInt(statusLine.substring(codeStart, codeStart + 3))
    }catch (e) {
      throw new ProtocolException("Unexpected status line: " + statusLine);
    }
    // Typescript引入的防御性编程
    if (Number.isNaN(code)){
      throw new ProtocolException("Unexpected status line: " + statusLine);
    }

    // Parse an optional response message like "OK" or "Not Modified". If it
    // exists, it is separated from the response code by a space.
    var message = ""
    if (statusLine.length > codeStart + 3) {
      if (statusLine[codeStart + 3] != ' ') {
        throw new ProtocolException("Unexpected status line: " + statusLine);
      }
      message = statusLine.substring(codeStart + 4)
    }

    return new StatusLine(protocol, code, message)
  }
}
